/*
 * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <hi_task.h>
#include <string.h>
#include <hi_wifi_api.h>
#include <hi_mux.h>
#include <hi_io.h>
#include <hi_gpio.h>
#include <hi_pwm.h>
#include <hi_adc.h>
#include <hi_i2c.h>
#include "iot_i2c.h"
#include "iot_config.h"
#include "iot_log.h"
#include "iot_main.h"
#include "iot_profile.h"
#include "iot_errno.h"   
#include "ohos_init.h"
#include "cmsis_os2.h"

//变量定义层*****************************************************************************************************************************************************************
/* attribute initiative to report */
#define TAKE_THE_INITIATIVE_TO_REPORT
#define ONE_SECOND                          (1000)
/* oc request id */
#define CN_COMMADN_INDEX                    "commands/request_id="
//#define WECHAT_SUBSCRIBE_LIGHT              "light"
//#define WECHAT_SUBSCRIBE_LIGHT_ON_STATE     "1"
//#define WECHAT_SUBSCRIBE_LIGHT_OFF_STATE    "0"
#define GY30_ADDR 0x23
#define GY30_COEFFICIENT_LUX 1.2

osThreadId_t ThreadHumanID;
osThreadId_t ThreadLightID;
osThreadId_t ThreadCloudID;

int g_ligthStatus = -1;
unsigned char Lux_data =0;
unsigned int HumanSensingVal;

unsigned char HumnanNumber =0;
unsigned char person_flag = 0;
unsigned char pwm_flag = 0;

extern unsigned char PersonLocateFlag;

typedef void (*FnMsgCallBack)(hi_gpio_value val);

typedef struct FunctionCallback {
    hi_bool  stop;
    hi_u32 conLost;
    hi_u32 queueID;
    hi_u32 iotTaskID;
    FnMsgCallBack    msgCallBack;
}FunctionCallback;
FunctionCallback g_functinoCallback;


//函数接口层*****************************************************************************************************************************************************************
//毫秒级延时函数
unsigned int TaskMsleep(unsigned int ms)
{
    if (ms <= 0) {
        return HI_ERR_FAILURE;
    }
    return hi_sleep((hi_u32)ms);
}

/***************************************************************
 * 函数名称: DeviceIO_Init
 * 说    明: 设备GPIO初始化
 * 参    数: 无
 * 返 回 值: 0 成功; -1 失败
 ***************************************************************/
static void DeviceIO_Init(void)      
{
    //LEDpwm初始化：
    hi_gpio_init();
    hi_io_set_func(HI_IO_NAME_GPIO_2,HI_IO_FUNC_GPIO_2_PWM2_OUT);
    hi_gpio_set_dir(HI_GPIO_IDX_2,HI_GPIO_DIR_OUT);
    hi_pwm_init(HI_PWM_PORT_PWM2);
    hi_pwm_set_clock(PWM_CLK_160M);
    

    hi_io_set_func(HI_IO_NAME_GPIO_8,HI_IO_FUNC_GPIO_8_PWM1_OUT);
    hi_gpio_set_dir(HI_GPIO_IDX_8,HI_GPIO_DIR_OUT);
    hi_pwm_init(HI_PWM_PORT_PWM1);
    hi_pwm_set_clock(PWM_CLK_160M);

    //RGB：PWM初始化
    hi_io_set_func(HI_IO_NAME_GPIO_6,HI_IO_FUNC_GPIO_6_PWM3_OUT);
    hi_gpio_set_dir(HI_GPIO_IDX_6,HI_GPIO_DIR_OUT);
    hi_pwm_init(HI_PWM_PORT_PWM3);
    hi_pwm_set_clock(PWM_CLK_160M);

    hi_io_set_func(HI_IO_NAME_GPIO_9,HI_IO_FUNC_GPIO_9_PWM0_OUT);
    hi_gpio_set_dir(HI_GPIO_IDX_9,HI_GPIO_DIR_OUT);
    hi_pwm_init(HI_PWM_PORT_PWM0);
    hi_pwm_set_clock(PWM_CLK_160M);

    hi_io_set_func(HI_IO_NAME_GPIO_10,HI_IO_FUNC_GPIO_10_PWM1_OUT);
    hi_gpio_set_dir(HI_GPIO_IDX_10,HI_GPIO_DIR_OUT);
    hi_pwm_init(HI_PWM_PORT_PWM1);
    hi_pwm_set_clock(PWM_CLK_160M);

    //人体感应传感器GPIO初始化
    hi_io_set_func(HI_IO_NAME_GPIO_7,HI_IO_FUNC_GPIO_7_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_7,HI_GPIO_DIR_IN);

    //数字光照传感器GPIO初始化(IIC通信)
    IoTGpioInit(13);
    IoTGpioInit(14);
    hi_io_set_func(HI_IO_NAME_GPIO_13,HI_IO_FUNC_GPIO_13_I2C0_SDA);
    hi_io_set_func(HI_IO_NAME_GPIO_14,HI_IO_FUNC_GPIO_14_I2C0_SCL);
    hi_i2c_init(HI_I2C_IDX_0,400000);
}

/***************************************************************
 * 函数名称: GY30_Init
 * 说    明: 写命令初始化GY30
 * 参    数: 无
 * 返 回 值: 0 成功; -1 失败
 ***************************************************************/
static int GY30_Init(void)
{
    int ret;
    uint8_t send_data[1] = { 0x01 };
    ret = IoTI2cWrite(HI_I2C_IDX_0, (GY30_ADDR << 1) | 0x00, send_data, 1);
    if (ret != 0) {
        printf("===== Error: I2C write ret = 0x%x! =====\r\n", ret);
        return -1;
    }
    return 0;
}

/***************************************************************
 * 函数名称: GY30_Start
 * 说    明: 启动GY30
 * 参    数: 无
 * 返 回 值: 0 成功; -1 失败
 ***************************************************************/
static int GY30_Start(void)
{
    int ret;
    uint8_t send_data[1] = { 0x10 };
    ret = IoTI2cWrite(HI_I2C_IDX_0, (GY30_ADDR << 1) | 0x00, send_data, 1);
    if (ret != 0) {
        printf("===== Error: I2C write ret = 0x%x! =====\r\n", ret);
        return -1;
    }
    return 0;
}

/***************************************************************
 * 函数名称: GY30_ReadData
 * 说    明: 写命令初始化GY30
 * 参    数: 无
 * 返 回 值: 0 成功; -1 失败
 ***************************************************************/
int GY30_ReadData()
{
    int ret;
    int result;
    ret = GY30_Start(); // 启动传感器采集数据
    if (ret != 0) {
        printf("Start GY30 failed!\r\n");
        return -1;
    }
    TaskMsleep(200);
    uint8_t recv_data[2] = { 0 };   
    ret = IoTI2cRead(HI_I2C_IDX_0, (GY30_ADDR << 1) | 0x01, recv_data, sizeof(recv_data)); // 读取传感器数据
    if (ret != 0) {
        printf("IoTI2cRead Failed!\r\n");
        return -1;
    }
    //printf("recv_data = %u\r\n",&recv_data[0]);
    //*data = recv_data[1];
    Lux_data = (float)(recv_data[0] + recv_data[1]) / GY30_COEFFICIENT_LUX; // 合成数据，即光照数据
    printf("data = %d\r\n",Lux_data);
    return 0;
}

static int  DeviceMsgCallback(FnMsgCallBack msgCallBack)
{
    g_functinoCallback.msgCallBack = msgCallBack;
    return 0;
}

static void wechatControlDeviceMsg(hi_gpio_value val)
{
    
}

//命令下发回调函数：
static void DemoMsgRcvCallBack(int qos, const char *topic, const char *payload)
{
    IOT_LOG_DEBUG("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", qos, topic, payload);
    /* 云端下发命令后，板端的操作处理 */

   //正常光（上课模式）
    if (strstr(payload, "light_a") != NULL) {
        if (strstr(payload, "1") != NULL) {
            hi_pwm_start(HI_PWM_PORT_PWM3, 120, 160);    //R 红色
            hi_pwm_start(HI_PWM_PORT_PWM0, 50, 160);  //G 绿色
            hi_pwm_start(HI_PWM_PORT_PWM1, 50, 160);  //B 蓝色 
        } else if (strstr(payload, "0") != NULL){
            hi_pwm_start(HI_PWM_PORT_PWM3, 1, 160);   //R 红色 
            hi_pwm_start(HI_PWM_PORT_PWM0, 1, 160);    //G 绿色
            hi_pwm_start(HI_PWM_PORT_PWM1, 1, 160);    //B 蓝色
        }
    } 

    //冷白光（自习模式）
    else if(strstr(payload, "light_b") != NULL) {
        if (strstr(payload, "1") != NULL) {
            hi_pwm_start(HI_PWM_PORT_PWM3, 100, 160);    
            hi_pwm_start(HI_PWM_PORT_PWM0, 80, 160);  
            hi_pwm_start(HI_PWM_PORT_PWM1, 70, 160);  
        } else if(strstr(payload, "0") != NULL) {
            hi_pwm_start(HI_PWM_PORT_PWM3, 1, 160);    
            hi_pwm_start(HI_PWM_PORT_PWM0, 1, 160);  
            hi_pwm_start(HI_PWM_PORT_PWM1, 1, 160);  
        }  
    }

    //暖白光（活动模式）
    else if (strstr(payload, "light_c") != NULL) {
        if (strstr(payload, "1") != NULL) {
            hi_pwm_start(HI_PWM_PORT_PWM3, 100, 160);  //100
            hi_pwm_start(HI_PWM_PORT_PWM0, 80, 160);  
            hi_pwm_start(HI_PWM_PORT_PWM1, 70, 160);  
        } else if(strstr(payload, "0") != NULL) {
            hi_pwm_start(HI_PWM_PORT_PWM3, 1, 160);    
            hi_pwm_start(HI_PWM_PORT_PWM0, 1, 160);  
            hi_pwm_start(HI_PWM_PORT_PWM1, 1, 160);  
        }
    }

    //else if (strstr(payload, "light1") != NULL) {
        //if (strstr(payload, 1) != NULL) {

        //} else {

        //}
    //}

    //else if (strstr(payload, "light2") != NULL) {
        //if (strstr(payload, 1) != NULL) {

        //} else {

        //}
    //}
    return HI_NULL;
}


//属性上报函数：
hi_void IotPublishSample(void)
{
    /* reported attribute */
    WeChatProfile weChatProfile = {
        .subscribeType = "type",
        .status.subState = "state",
        .status.subReport = "reported",
        .status.reportVersion = "version",
        .status.Token = "clientToken",
        /* report humidity */
        .reportAction.subDeviceActionHumidity = "humidity",
        .reportAction.humidityActionData = HumnanNumber,
        /* report light_intensity */
        .reportAction.subDeviceActionLightIntensity = "light_intensity",
        .reportAction.lightIntensityActionData = Lux_data , 
    };
    /* profile report */
    IoTProfilePropertyReport(CONFIG_USER_ID, &weChatProfile);
}


//业务层*****************************************************************************************************************************************************************
//业务1：人体感应
static hi_void *HumanSensingEntry(const char *arg){
    while (1)
    {
        hi_gpio_get_input_val(HI_GPIO_IDX_7, &HumanSensingVal);
        printf("HuamnSensingVal = %d\r\n", (unsigned int)HumanSensingVal);
        if(HumanSensingVal == 1){
            HumnanNumber = person_flag++;
            printf("HumnanNumber = %d",HumnanNumber);
            if(pwm_flag == 0){
                hi_pwm_start(HI_PWM_PORT_PWM2, 20, 160);
                hi_pwm_start(HI_PWM_PORT_PWM1, 20, 160);
                pwm_flag++;
            }
            
            //osThreadSuspend(ThreadHumanID);
        }
        TaskMsleep(1000);
    }
}


//业务2：自适应调光（根据光强）
static hi_void *LightSensingEntry(const char *arg){

    int ret;
    unsigned int duty;

    while (1)
    {
        ret = GY30_ReadData();            //&Lux
        if (ret != 0) {
            printf("GY30 Read Data failed!\r\n");
            return;
        }

        usleep(1000000);

        //根据光的照度——pwm自适应调光   注意：pwm2和pwm3保持相同   pwm1作为重点区域LED

        // if(Lux_data >25){
        //     if(HumnanNumber <= 5){
        //         if(PersonLocateFlag > 100){
        //             hi_pwm_start(HI_PWM_PORT_PWM1, 1, 160);
        //             hi_pwm_start(HI_PWM_PORT_PWM2, 20, 160);
        //         }
        //         else{
        //             hi_pwm_start(HI_PWM_PORT_PWM1, 40, 160);
        //             hi_pwm_start(HI_PWM_PORT_PWM2, 20, 160);
        //         }
        //     }
        //     else{
        //         hi_pwm_start(HI_PWM_PORT_PWM1, 20, 160);
        //         hi_pwm_start(HI_PWM_PORT_PWM2, 20, 160);
        //     }
            
        // }
        // else if(Lux_data < 25 && Lux_data > 10){
        //     if(HumnanNumber <= 5){
        //         if(PersonLocateFlag > 100){
        //             hi_pwm_start(HI_PWM_PORT_PWM1, 40, 160);
        //             hi_pwm_start(HI_PWM_PORT_PWM2, 100, 160);
        //         }
        //         else{
        //             hi_pwm_start(HI_PWM_PORT_PWM1, 100, 160);
        //             hi_pwm_start(HI_PWM_PORT_PWM2, 40, 160);
        //         }
        //     }
        //     else{
        //         hi_pwm_start(HI_PWM_PORT_PWM1, 100, 160);
        //         hi_pwm_start(HI_PWM_PORT_PWM2, 100, 160);
        //     }
        // }
        // else{
        //     if(HumnanNumber <= 5){
        //         if(PersonLocateFlag > 100){
        //             hi_pwm_start(HI_PWM_PORT_PWM1, 20, 160);
        //             hi_pwm_start(HI_PWM_PORT_PWM2, 160, 160);
        //         }
        //         else{
        //             hi_pwm_start(HI_PWM_PORT_PWM1, 160, 160);
        //             hi_pwm_start(HI_PWM_PORT_PWM2, 20, 160);
        //         }
        //     }
        //     else{
        //         hi_pwm_start(HI_PWM_PORT_PWM1, 160, 160);
        //         hi_pwm_start(HI_PWM_PORT_PWM2, 160, 160);
        //     }
        // }
    }
}


//业务3：属性上报与命令下发控制
static hi_void *CloudEntry(const char *arg)
{
    WifiStaReadyWait();   //wifi准备
    cJsonInit();          //cJson数据初始化
    IoTMain();
    IoTSetMsgCallback(DemoMsgRcvCallBack);    //命令下发回调

    /* 属性主动上报 */
#ifdef TAKE_THE_INITIATIVE_TO_REPORT
    while (1) {
        IotPublishSample(); // 属性上报接口
#endif
        TaskMsleep(ONE_SECOND);
    }
    return NULL;
}


//主业务入口：
static void MainEntry(void)
{
    int ret;

    //设备初始化：
    DeviceIO_Init();
    ret = GY30_Init();
    if (ret != 0) {
        printf("GY30 Init failed!\r\n");
        return;
    }

    IoTWatchDogDisable();

    osThreadAttr_t attr;

    attr.name = "HumanSensingEntry";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 0x4096;
    attr.priority = 25;

    //业务1：
    ThreadHumanID = osThreadNew((osThreadFunc_t)HumanSensingEntry, NULL, &attr);
    if (ThreadHumanID == NULL) {
        printf("Falied to create HumanSensingEntry!\n");
    }

    //业务2：
    attr.name = "LightSensingEntry";
    ThreadLightID = osThreadNew((osThreadFunc_t)LightSensingEntry, NULL, &attr);
    if (ThreadLightID == NULL) {
        printf("Falied to create LightSensingEntry!\n");
    }

    //业务3：
    attr.name = "CloudEntry";
    ThreadCloudID = osThreadNew((osThreadFunc_t)CloudEntry, NULL, &attr);
    if (ThreadCloudID == NULL) {
        printf("Falied to create CloudEntry!\n");
    }


}

SYS_RUN(MainEntry);